package com.colin.log.dubbo;

import com.alibaba.dubbo.rpc.Filter;
import com.alibaba.dubbo.rpc.Invocation;
import com.alibaba.dubbo.rpc.Invoker;
import com.alibaba.dubbo.rpc.Result;
import com.alibaba.dubbo.rpc.RpcContext;
import com.alibaba.dubbo.rpc.RpcException;
import com.alibaba.dubbo.rpc.RpcInvocation;
import com.alibaba.dubbo.rpc.protocol.dubbo.DecodeableRpcInvocation;
import com.alibaba.fastjson.JSONObject;
import com.colin.log.util.IdUtil;
import com.colin.log.util.LogUtil;
import org.slf4j.MDC;

/**
 * Dubbo调用链路日志
 * 需要在dubbo配置文件中配置
 * 在provider配置<dubbo:provider filter="dubboLogFilter" />
 * 在consumer配置<dubbo:consumer filter="dubboLogFilter" />
 * 若一个项目既是provider又是consumer则都配置即可
 */ 
public class DubboLogFilter implements Filter {

    @Override
    public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
        //日志默认参数设置
        if (invocation instanceof DecodeableRpcInvocation) {
            provider(invocation);
        } else if (invocation instanceof RpcInvocation) {
            consumer(invocation);
        }
        //请求信息
        long begin = System.currentTimeMillis();
        Object[] args = invocation.getArguments();
        LogUtil.printSelectiveLog("dubbo invoke param:{}", args);
        
        Result r = invoker.invoke(invocation);
        
        //响应信息
        long end = System.currentTimeMillis();
        if(r.hasException()){
            LogUtil.error("dubbo invoke exception:", r.getException());
        }else{
            LogUtil.info("dubbo invoke success:{}", JSONObject.toJSONString(r));
        }
        LogUtil.info("dubbo invoke rt:{}", end-begin);
        
        return r;
    }

    /**
     * 提供者处理
     */
    private void provider(Invocation invocation) {
        String traceId = invocation.getAttachment(LogUtil.LOG_PARAM_TRACE_ID);
        if (traceId == null || traceId.length() == 0) {
            traceId = IdUtil.getUUID();
        }
        MDC.put(LogUtil.LOG_PARAM_TRACE_ID, traceId);
        String clientIp = RpcContext.getContext().getRemoteAddress().getHostString();
        MDC.put(LogUtil.LOG_PARAM_CLIENT_IP, clientIp);
    }

    /**
     * 消费者处理
     */
    private void consumer(Invocation invocation){
        RpcInvocation rpcInvocation = (RpcInvocation) invocation;
        String traceId = MDC.get(LogUtil.LOG_PARAM_TRACE_ID);
        if (traceId == null || traceId.length() == 0) {
            traceId = IdUtil.getUUID();
        }
        rpcInvocation.setAttachment(LogUtil.LOG_PARAM_TRACE_ID, traceId);
    }
    
}
